module ExprAM 						
	where							
import ExprDataTypes				
import CalVar											
import Extras
import OptObjeto


	
passCod :: [ComboTuple] -> (VarMap, [(TInstruccionAM, Integer)])
passCod ast = ((vs++extraStackValues),  optObjeto (nuevaFuncion (fst instrucciones) vs))
              where 
                (vs, n) = calvariables (map fst ast) (-1) 
                instrucciones = passCodigo ast vs (snd (last ast)) 1
                    --instrucciones = passCodigo ast vs (snd (last ast)) 

passCodigo :: [ComboTuple] -> VarMap -> Tipo -> Integer -> ([(TInstruccionAM, Integer)],Integer)
passCodigo [x] vs tb nAc = genCodigo x vs 0 tb nAc
passCodigo (x:xs) vs tb nAc = ( v ++ mPop ++ v2, nf2)
    where
        (v,n1) = genCodigo x vs 0 "" nAc
        (v2,nf2) = passCodigo xs vs tb n1

genCodigo :: ComboTuple -> VarMap -> Integer -> String -> Integer -> ([(TInstruccionAM, Integer)],Integer)

genCodigo ((Mas a b), mt) vs n lqedm nLab = ( 
    bloqa ++
    bloqb ++
    mAdd ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo b vs n mt nLab 
        (bloqa,n2) = genCodigo a vs n mt n1

genCodigo ((Menos a b), mt) vs n lqedm nLab = ( 
    bloqa ++
    bloqb ++
    mSub ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo b vs n mt nLab 
        (bloqa,n2) = genCodigo a vs n mt n1

genCodigo ((Por a b), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mMult ++ 
    codCoercion mt lqedm vs ,
    n2)
    where 
        (bloqb,n1) = genCodigo b vs n mt nLab 
        (bloqa,n2) = genCodigo a vs n mt n1

genCodigo ((Div a b), mt) vs n lqedm nLab  = ( 
    bloqa ++
    bloqb ++
    mDiv ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo b vs n mt nLab 
        (bloqa,n2) = genCodigo a vs n mt n1

genCodigo ((Igual (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mEq ++ 
    codCoercion mt lqedm vs,
    n2)--VERIFICAR
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,tb) vs n ta n1

genCodigo ((Distinto (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mEq ++ 
    mPush 0 ++ 
    mEq ++ 
    codCoercion mt lqedm vs,
    n2) --VERIFICAR
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((Menor (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mLt ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b, tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((Mayor (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mGt ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((MayorIgual (a, ta) (b, tb)), mt) vs n lqedm nLab  = (
    bloqa ++
    bloqb ++
    mLt ++ 
    mPush 0 ++ 
    mEq ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((MenorIgual (a, ta) (b, tb)), mt) vs n lqedm nLab  = (
    bloqa ++
    bloqb ++
    mGt ++ 
    mPush 0 ++ 
    mEq ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((Parentesis a), mt) vs n lqedm nLab  = 
    genCodigo a vs n lqedm nLab

genCodigo ((OAnd (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mAnd ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((OOr (a, ta) (b, tb)), mt) vs n lqedm nLab = (
    bloqa ++
    bloqb ++
    mOr ++ 
    codCoercion mt lqedm vs,
    n2)
    where 
        (bloqb,n1) = genCodigo (b,tb) vs n tb nLab 
        (bloqa,n2) = genCodigo (a,ta) vs n ta n1

genCodigo ((ONot a), mt) vs n lqedm nLab = (
    bloqa ++
    mPush 0 ++ 
    mEq,
    n1)
    where
        (bloqa,n1) = genCodigo a vs n mt nLab

genCodigo ((Id a), mt) vs n lqedm nLab = (
    mFetch a vs ++ 
    codCoercion mt lqedm vs,
    nLab)

genCodigo ((Asignacion a b), mt) vs n lqedm nLab  = (
    bloqb ++
    mDup ++ 
    mStore a vs ++ 
    codCoercion mt lqedm vs,
    n1)
    where
        (bloqb,n1) = genCodigo b vs n mt nLab
    -- EL DUP NO FUNCA AHORA

genCodigo ((Declaracion tipo var (EOpc a)), mt) vs n lqedm nLab  = (
    bloqa ++ 
    mDup ++ 
    mStore var vs ++ 
    codCoercion mt lqedm vs,
    n1)
    where
        (bloqa,n1) = genCodigo a vs n mt nLab
    
    --EL DUP NO FUNCA AHORA

genCodigo (Write a, mt) vs n lqedm nLab = (
    mFetch a vs ++ 
    mDup ++ 
    mWrite a vs ++ 
    codCoercion mt lqedm vs,
    nLab)

genCodigo ((Read), mt) vs n lqedm nLab = (
    mRead,
    nLab)

genCodigo ((Length a), mt) vs n lqedm nLab  = (
    mFetch a vs ++ 
    mLength a vs ++ 
    codCoercion mt lqedm vs,
    nLab)

genCodigo ((Iteracion (cond, tc) a (BElse b)), mt) vs n lqedm nLab = (
    bloqPriCond ++              -- se prueba la Condiciona 
    mFcjp "WE" num ++           -- si da false va al else sino continua
    mLabel "WC" num ++          
	bloqa ++                    -- se ejecuta la el bloque del while
	bloqSegCond ++              -- se ejecuta condicion. si da false sale
    mFcjp "WO" num ++
	mUjp "WC" num ++            -- si da true entonces vuelve a ejecutar el bucle
    mLabel "WE" num ++
	bloqb ++                    -- Bloque else 
    mLabel "WO" num ++
	mNop, 
    n4)
    where 
        num = nLab
        (bloqPriCond,n1) = genCodigo (cond,tc) vs n tc (nLab + 1) 
        (bloqSegCond,n3) = genCodigo (cond,tc) vs n tc n2 
        (bloqb,n2) = passCodigo b vs mt n1 
        (bloqa,n4) = passCodigo a vs mt n3
          
genCodigo ((Condicional (cond, tc) a (BElse b)), mt) vs n lqedm nLab = (
    bloqCond ++ 
    mFcjp "IT" num ++ 
    bloqa ++ 
    mUjp "IE" num ++ 
    mLabel "IT" num ++ 
    bloqb ++ 
    mLabel "IE" num ++ 
    mNop,
    n3)
    where num = nLab
          --(bloqCond,n1) = genCodigo (ONot cond) vs n (nLab + 1)
          (bloqCond,n1) = genCodigo (cond,tc) vs n tc (nLab + 1)
          (bloqb,n3) = passCodigo b vs mt n2
          (bloqa,n2) = passCodigo a vs mt n1
        
genCodigo (c, mt) vs n lqedm nLab = (mPushG c lqedm, nLab)
